﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using System.ComponentModel;

using Seven.Core.IRepositories;
using Seven.EntityBasic;
using Seven.Service.Security;
using Seven.Tools.Extension;
using Seven.Tools.Helper;
using Seven.Tools.ComponentModel.Paging;
using Seven.Web.IntelligentQuery.Model;
using Seven.Web.IntelligentQuery.Converter;

namespace Seven.Service.Powerful
{
    /// <summary>
    /// 基本业务基类
    /// </summary>
    /// <typeparam name="TEntity">实体类型</typeparam>
    /// <typeparam name="TKey">TEntity实体的主键类型</typeparam>
    public abstract class BaseService<TEntity, TKey>
        where TKey : struct
        where TEntity : EntityBase<TKey>
    {
        #region 当前登录用的信息 由于service工厂会将service实例存储在静态变量中以便下次使用，会导致以下成员无法正常起作用。为解决该问题，暂时把“工厂中存储service实例”的功能去掉，每次都new一个service实例。

        private UserInfoModel _CurrentUserBaseInfo;

        private IEnumerable<Seven.Entity.HrOrganization> _CurrentUserOrganRange;

        private IEnumerable<Seven.Entity.SysMenu> _CurrentUserMenuRange;

        private IEnumerable<Seven.Entity.SysMenuPermission> _CurrentUserMenuPermissionRange;

        private IEnumerable<Seven.Entity.SysMenuFunction> _CurrentUserMenuFunctionRange;

        /// <summary>
        /// 当前登录用户信息集合（不包含范围信息）
        /// </summary>
        public UserInfoModel CurrentUserBaseInfo
        {
            get { if (_CurrentUserBaseInfo == null) { _CurrentUserBaseInfo = new Account().GetCurrentUserBaseInfo(); } return _CurrentUserBaseInfo; }
        }

        /// <summary>
        /// 当前用户的可管理的组织结构范围
        /// </summary>
        public IEnumerable<Seven.Entity.HrOrganization> CurrentUserOrganRange
        {
            get { if (_CurrentUserOrganRange == null) { _CurrentUserOrganRange = new Account().GetCurrentUserOrganRange(); } return _CurrentUserOrganRange; }
        }

        /// <summary>
        /// 当前用户的可管理的公司范围
        /// </summary>
        public IEnumerable<Seven.Entity.HrOrganization> CurrentUserCompanyRange
        {
            get
            {
                if (_CurrentUserOrganRange == null) { _CurrentUserOrganRange = new Account().GetCurrentUserOrganRange(); }
                return _CurrentUserOrganRange.Where(w => w.Type == OrganType.公司).TryOrderBy(o => o.SortNumber);
            }
        }

        /// <summary>
        /// 当前用户的有权使用的菜单权限范围
        /// </summary>
        protected IEnumerable<Seven.Entity.SysMenuPermission> CurrentUserMenuPermissionRange
        {
            get { if (_CurrentUserMenuPermissionRange == null) { _CurrentUserMenuPermissionRange = new Account().GetCurrentUserMenuPermissionRange(); } return _CurrentUserMenuPermissionRange; }
        }

        /// <summary>
        /// 当前用户的有权使用的菜单功能点范围
        /// </summary>
        protected IEnumerable<Seven.Entity.SysMenuFunction> CurrentUserMenuFunctionRange
        {
            get { if (_CurrentUserMenuFunctionRange == null) { _CurrentUserMenuFunctionRange = new Account().GetCurrentUserMenuFunctionRange(); } return _CurrentUserMenuFunctionRange; }
        }

        /// <summary>
        /// 当前用户的有权使用的菜单范围
        /// </summary>
        protected IEnumerable<Seven.Entity.SysMenu> CurrentUserMenuRange
        {
            get { if (_CurrentUserMenuRange == null) { _CurrentUserMenuRange = new Account().GetCurrentUserMenuRange(); } return _CurrentUserMenuRange; }
        }

        #endregion

        #region 数据查询

        #region 查询单个

        /// <summary>
        /// 主键查询
        /// </summary>
        /// <param name="key">主键</param>
        /// <returns>实体</returns>
        public TEntity GetByKey(TKey key)
        {
            using (var db = DbFactory.UnitOfWork)
            {
                var rep = db.GetRepository<TEntity, TKey, IBaseRepository<TEntity, TKey>>();

                return rep.Find(key);
            }
        }

        #endregion

        #endregion

        #region 数据操作

        #region 添加

        /// <summary>
        /// 添加实体
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns>操作结果</returns>
        public virtual OperationResult Insert(TEntity entity)
        {
            using (var unit = DbFactory.UnitOfWork)
            {
                var rep = unit.GetRepository<TEntity, TKey, IBaseRepository<TEntity, TKey>>();

                try
                {
                    unit.BeginTransaction();
                    rep.EntityAdded(entity);
                    var msg = new string[] { "添加成功!", "添加失败!" };
                    return new OperationResult(unit.Commit() > 0, msg);
                }
                catch (DataAccessException ex)
                {
                    unit.Rollback();
                    throw ExceptionHelper.ThrowServiceException(ex.Message);
                }
            }
        }

        /// <summary>
        /// 批量添加实体
        /// </summary>
        /// <param name="entities">实体集合</param>
        /// <returns>操作结果</returns>
        public virtual OperationResult Insert(IEnumerable<TEntity> entities)
        {
            if (entities.Count() == 0) { return new OperationResult(true); }
            using (var unit = DbFactory.UnitOfWork)
            {
                var rep = unit.GetRepository<TEntity, TKey, IBaseRepository<TEntity, TKey>>();

                try
                {
                    unit.BeginTransaction();
                    rep.EntitiesAdded(entities);
                    var msg = new string[] { "批量添加成功!", "批量添加失败!" };
                    return new OperationResult(unit.Commit() > 0, msg);
                }
                catch (DataAccessException ex)
                {
                    unit.Rollback();
                    throw ExceptionHelper.ThrowServiceException(ex.Message);
                }
            }
        }

        #endregion

        #region 更改

        /// <summary>
        /// 更改实体
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns>操作结果</returns>
        public virtual OperationResult Update(TEntity entity)
        {
            using (var unit = DbFactory.UnitOfWork)
            {
                var rep = unit.GetRepository<TEntity, TKey, IBaseRepository<TEntity, TKey>>();

                try
                {
                    unit.BeginTransaction();
                    rep.EntityModified(entity);
                    var msg = new string[] { "更新成功!", "更新失败!" };
                    return new OperationResult(unit.Commit() > 0, msg);
                }
                catch (DataAccessException ex)
                {
                    unit.Rollback();
                    throw ExceptionHelper.ThrowServiceException(ex.Message);
                }
            }
        }

        /// <summary>
        /// 批量更改实体
        /// </summary>
        /// <param name="entity">实体集合</param>
        /// <returns>操作结果</returns>
        public virtual OperationResult Update(IEnumerable<TEntity> entities)
        {
            if (entities.Count() == 0) { return new OperationResult(true); }
            using (var unit = DbFactory.UnitOfWork)
            {
                var rep = unit.GetRepository<TEntity, TKey, IBaseRepository<TEntity, TKey>>();

                try
                {
                    unit.BeginTransaction();
                    rep.EntitiesModified(entities);
                    var msg = new string[] { "批量更新成功!", "批量更新失败!" };
                    return new OperationResult(unit.Commit() > 0, msg);
                }
                catch (DataAccessException ex)
                {
                    unit.Rollback();
                    throw ExceptionHelper.ThrowServiceException(ex.Message);
                }
            }
        }

        #endregion

        #region 删除

        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns>操作结果</returns>
        public OperationResult Delete(TEntity entity)
        {
            using (var unit = DbFactory.UnitOfWork)
            {
                var rep = unit.GetRepository<TEntity, TKey, IBaseRepository<TEntity, TKey>>();

                try
                {
                    unit.BeginTransaction();
                    rep.EntityDeleted(entity);
                    var msg = new string[] { "删除成功!", "删除失败!" };
                    return new OperationResult(unit.Commit() > 0, msg);
                }
                catch (DataAccessException ex)
                {
                    unit.Rollback();
                    throw ExceptionHelper.ThrowServiceException(ex.Message);
                }
            }
        }

        /// <summary>
        /// 主键删除实体
        /// </summary>
        /// <param name="key">键值</param>
        /// <returns>操作结果</returns>
        public OperationResult Delete(TKey key)
        {
            using (var unit = DbFactory.UnitOfWork)
            {
                var rep = unit.GetRepository<TEntity, TKey, IBaseRepository<TEntity, TKey>>();

                try
                {
                    unit.BeginTransaction();
                    rep.EntityDeleted(key);
                    var msg = new string[] { "删除成功!", "删除失败!" };
                    return new OperationResult(unit.Commit() > 0, msg);
                }
                catch (DataAccessException ex)
                {
                    unit.Rollback();
                    throw ExceptionHelper.ThrowServiceException(ex.Message);
                }
            }
        }

        /// <summary>
        /// 批量删除实体
        /// </summary>
        /// <param name="entities">实体</param>
        /// <returns>操作结果</returns>
        public OperationResult Delete(IEnumerable<TEntity> entities)
        {
            if (entities.Count() == 0) { return new OperationResult(true); }
            using (var unit = DbFactory.UnitOfWork)
            {
                var rep = unit.GetRepository<TEntity, TKey, IBaseRepository<TEntity, TKey>>();

                try
                {
                    unit.BeginTransaction();
                    rep.EntitiesDeleted(entities);
                    var msg = new string[] { "批量删除成功!", "批量删除失败!" };
                    return new OperationResult(unit.Commit() > 0, msg);
                }
                catch (DataAccessException ex)
                {
                    unit.Rollback();
                    throw ExceptionHelper.ThrowServiceException(ex.Message);
                }
            }
        }

        #endregion

        #endregion
    }
}
